﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.IO;

namespace WebRamosUC.Models
{
    public class RepositorioUsuario : IMembershipService
    {
        private WebRamosUCDataContext db;

         public  RepositorioUsuario(WebRamosUCDataContext dataContext)
        {
             this.db = dataContext;
        }
         public RepositorioUsuario()
         {
            db = new WebRamosUCDataContext();
         }

        public string webUrl = "http://www.webramosuc.cl";

        /// <summary>
        /// Agrega un usuario.
        /// </summary>
        public void Add(Usuario usuario)
        {
            db.Usuarios.InsertOnSubmit(usuario);
        }

        public string imageName(string userMail, string folderPath)
        {
            string[] files = Directory.GetFiles(folderPath, userMail+".*");

            string retorno;

            if (files.Length > 0)
                retorno = files[0];
            else
                retorno = folderPath+"\\none.gif";

            return retorno;
        }

        public Usuario getUserByName(string userName)
        {
            return db.Usuarios.SingleOrDefault(us => us.Nombre == userName);
        }

        /// <summary>
        /// Modifica el correo del usuario
        /// </summary>
        public Boolean ChangeCorreo(Usuario usuario, String Newcorreo)
        {
            
            if ( usuario != null)
            {
                usuario.Correo = Newcorreo;
                return true;
            }

            else
                return false;

        }

        /// <summary>
        /// Borra de la base de datos al usuario.
        /// </summary>
        public Boolean DeleteUser(Usuario usuario) 
        {
            if (usuario != null)
            {
                db.Usuarios.DeleteOnSubmit(usuario);
                return true;
            }

            else
                return false;
        }

        /// <summary>
        /// Guarda los cambios.
        /// </summary>
        public void Save()
        {
            db.SubmitChanges();
        }

        /// <summary>
        /// Retorna el mail de un nombre de usuario
        /// </summary>
        public string GetMailByName(string Nombre)
        {
            return db.Usuarios.SingleOrDefault(usuario => usuario.Nombre == Nombre).Correo;
        }

        /// <summary>
        /// Retorna el nombre de usuario de un mail
        /// </summary>
        public string GetNameByMail(string Mail)
        {
            return db.Usuarios.SingleOrDefault(usuario => usuario.Correo == Mail).Nombre;
        }

        /// <summary>
        /// Retorna el usuario siempre y cuando le hayan acertado al mail y pass
        /// </summary>
        public Usuario LoginByMail(string mail, string pass)
        {
            return db.Usuarios.SingleOrDefault(us => (us.Correo == mail && us.Contrasenia == pass));
        }

        /// <summary>
        /// Retorna el usuario siempre y cuando le hayan acertado al mail y pass
        /// </summary>
        public int GetIdByName(string name)
        {
            return db.Usuarios.SingleOrDefault(us => us.Nombre == name ).IDUsuario;
        }

        /// <summary>
        /// Genera el codigo para validacion de un usuario
        /// </summary>
        public int GenerarCodigoValidacionUsuario()
        {
            int codigo = 0;
            bool yaEsta = true;
            while (yaEsta)
            {
                Random ran = new Random();
                codigo = ran.Next(10000, 99999);

                yaEsta = db.Usuarios.Any(user => user.Validado == codigo);
            }
            return codigo;
        }

        /// <summary>
        /// Retorna si el usuario esta activo o no
        /// </summary>
        public bool UsuarioActivo(string userMail)
        {
            try
            {
                Usuario user = db.Usuarios.SingleOrDefault(usu => usu.Correo == userMail);

                return user.Validado == 0;
            }
            catch 
            { 
                //NO DEBERIA CAER NUNCA AQUI
                return false;
            }
        }

        /// <summary>
        /// Activa algun usuario que este con codigo de activacion, retorna si se pudo o no, y out el nombre de quien era, envia un mail con la informacion
        /// </summary>
        public bool ActivarUsuario(int codigo, out string userName)
        {
            try
            {
                Usuario user = db.Usuarios.SingleOrDefault(usu => usu.Validado == codigo);
                user.Validado = 0;
                Save();
                userName = user.Nombre;
                EnviarInfoMail(user);
                return true;
            }
            catch { userName = "";  return false; }
        }

        /// <summary>
        /// Envia la informacion de un usuario a su mail
        /// </summary>
        public void EnviarInfoMail(Usuario usuario)
        {
            string body = "Su cuenta de Web Ramos UC se encuentra activa.";
            body += "\n\nSus datos son:\n";
            body += "\n\nNombre: "+usuario.Nombre;
            body += "\n\nCorreo: "+usuario.Correo;
            body += "\n\nContraseña: " + usuario.Contrasenia;
            Mail mail = new Mail();
            mail.enviarMail(usuario.Correo, usuario.Nombre, "Información Cuenta Web Ramos UC", body);
            
        }

        /// <summary>
        /// Envia mail de verificacion para activar usuario
        /// </summary>
        public void EnviarVerificacion(string userMail)
        {
            try
            {
                Usuario aux = db.Usuarios.SingleOrDefault(user => user.Correo == userMail);

                EnviarVerificacion(aux);
            }
            catch{ throw new ArgumentException("No existe un usuario con ese correo"); }
        }

        /// <summary>
        /// Envia mail de verificacion para activar usuario
        /// </summary>
        public void EnviarVerificacion(Usuario usuario)
        {
            
             //TODO: NO SE COMO PONER la direccion url de la aplicacion
            string link = webUrl + "/Account/Activar/" + usuario.Validado;
            string body = "Gracias por registrarte en Web Ramos UC. Este es el ultimo paso para activar tu cuenta.";
            body += "\n\nDirigete al siguiente link para activarla: \n\n" + link;
            body += "\n\nSi no funciona el link, ingresa a: \n\n" + webUrl + "/Account/Activar/0";
            body += "\n\nY ingresa el codigo de verificacion, sin espacios extras.";
            body += "\n\nCodigo de verificacion: " + usuario.Validado;
            Mail mail = new Mail();
            mail.enviarMail(usuario.Correo, usuario.Nombre, "Activación de Cuenta Web Ramos UC", body);
        }

        /// <summary>
        /// Genera una nueva pass para el usuario, se lo envia al correo
        /// </summary>
        public void EnviarPassAlMail(string userMail)
        {
            try
            {
                Usuario usuario = db.Usuarios.SingleOrDefault(user => user.Correo == userMail);

                string newPass = RandomString(6);

                ChangePassword(usuario.Nombre, usuario.Contrasenia, newPass);

                string body = "Usted ha solicitado que se le envie la contraseña al mail, por tema de seguridad se ha autogenerado una nueva.";
                body += "\n\nLos datos son los siguientes:";
                body += "\n\nCorreo electrónico: "+userMail;
                body += "\n\nContraseña: "+newPass;
                Mail mail = new Mail();
                mail.enviarMail(usuario.Correo, usuario.Nombre, "Activación de Cuenta Web Ramos UC", body);
            }
            catch { throw new ArgumentException("No existe un usuario con ese correo"); }
        }

        /// <summary>
        /// Genera un string aleatorio del largo dado, de numeros y letras minusculas
        /// </summary>
        public string RandomString(int largo)
        {
            string aux = "";
            Random ran = new Random();

            for (int i = 0; i < largo; i++)
            {
                int a = ran.Next(35);
                if(a<26)
                    aux += (char)(97 + a);
                else
                    aux+= (a-25);
            }

            return aux;
        }

        // IMPLEMENTANDO IMembershipService
        #region IMembershipServie
        public int MinPasswordLength
        {
            get { return 6; }
        }

        public bool ValidateUser(string userName, string password)
        {
            // EN VERDAD ES EL CORREO, NO EL NOMBRE

            try
            {
                Usuario u = db.Usuarios.SingleOrDefault(usuaro => usuaro.Correo == userName);

                return u.Contrasenia == password;
            }
            catch { throw new ArgumentException("No existe el usuario con ese correo"); }
        }

        public System.Web.Security.MembershipCreateStatus CreateUser(string userName, string password, string email)
        {
            if (userName == null || userName.Length < 4)
                return System.Web.Security.MembershipCreateStatus.InvalidUserName;
            else if (email == null || !(email.Contains("@") && email.Contains('.')))
                return System.Web.Security.MembershipCreateStatus.InvalidEmail;
            else if (password == null || password.Length < 6)
                return System.Web.Security.MembershipCreateStatus.InvalidPassword;
            else if (db.Usuarios.Any(usuario => usuario.Nombre == userName))
                return System.Web.Security.MembershipCreateStatus.DuplicateUserName;
            else if (db.Usuarios.Any(usuario => usuario.Correo == email))
                return System.Web.Security.MembershipCreateStatus.DuplicateEmail;
            else
            {
                int codigo = GenerarCodigoValidacionUsuario();

                Usuario usuario = new Usuario() {Nombre = userName, Correo = email, Contrasenia = password, Validado = codigo};
                

                db.Usuarios.InsertOnSubmit(usuario);
                Save();

                //Mail de verificacion
                EnviarVerificacion(usuario);

                
                return System.Web.Security.MembershipCreateStatus.Success;
            }
        }

        public bool ChangePassword(string userName, string oldPassword, string newPassword)
        {
            try
            {
                Usuario usuario = db.Usuarios.SingleOrDefault(us => us.Nombre == userName);

                if (usuario.Contrasenia == oldPassword)
                {
                    usuario.Contrasenia = newPassword;
                    Save();
                    return true;
                }
                else
                    return false;
            }
            catch
            {
                return false;
            }
        }
        #endregion


        #region Inscripcion de cursos...

        /// <summary>
        /// Inscribe el usuario a la seccion.
        /// </summary>
        public void AddInscripcion(string userName, int idSeccion)
        {
            Usuario usuario = getUserByName(userName);

            if (usuario == null  || usuario.IDUsuario == 0 || idSeccion == 0)
                throw new ArgumentException("Usuario o seccion son invalidos.");

            if (usuario.GetSeccionesInscritas().Any(sec => sec.IDSeccion == idSeccion))  //El usuario ya esta inscrito.
                return;

            UsuarioSeccion us = new UsuarioSeccion();
            us.IDUsuario = usuario.IDUsuario;
            us.IDSeccion = idSeccion;
            db.UsuarioSeccions.InsertOnSubmit(us);
            db.SubmitChanges();
        }

        /// <summary>
        /// Desinscribe el usuario a la seccion.
        /// </summary>
        public void DeleteInscripcion(string userName, int idSeccion)
        {
            Usuario usuario = getUserByName(userName);

            if (usuario == null || usuario.IDUsuario == 0 || idSeccion == 0)
                throw new ArgumentException("Usuario o seccion son invalidos.");

            UsuarioSeccion us = usuario.UsuarioSecciones.SingleOrDefault(x => x.Usuario == usuario && x.IDSeccion == idSeccion);
            
            db.UsuarioSeccions.DeleteOnSubmit(us);  //Lo borro permanentemente de la DB! Ojala no le moleste a Mery =)
            db.SubmitChanges();
        }

        /// <summary>
        /// Indica si el usuario se ha inscrito a la seccion.
        /// </summary>
        public bool UserHasSuscribed(Seccion seccion, string userName)
        {
            Usuario usuario = getUserByName(userName);

            if (usuario == null || usuario.IDUsuario == 0 || seccion == null || seccion.IDSeccion == 0)
                throw new ArgumentException("Usuario o seccion son invalidos.");

            return usuario.GetSeccionesInscritas().Any(sec => sec.IDSeccion == seccion.IDSeccion);  //El usuario ya esta inscrito.
        }
        #endregion
    }
}